/*
 * OgreMax Sample Viewer and Scene Loader - Ogre3D-based viewer and code for loading and displaying .scene files
 * Copyright 2010 AND Entertainment
 *
 * This code is available under the OgreMax Free License:
 *   -You may use this code for any purpose, commercial or non-commercial.
 *   -If distributing derived works (that use this source code) in binary or source code form, 
 *    you must give the following credit in your work's end-user documentation: 
 *        "Portions of this work provided by OgreMax (www.ogremax.com)"
 *
 * AND Entertainment assumes no responsibility for any harm caused by using this code.
 * 
 * The OgreMax Sample Viewer and Scene Loader were released at www.ogremax.com 
 */


#ifndef OgreMax_Joystick_INCLUDED
#define OgreMax_Joystick_INCLUDED


//Includes---------------------------------------------------------------------
#include <OIS.h>
#include "InputSource.hpp"


//Classes----------------------------------------------------------------------
namespace OgreMax
{
    /**
     * Wrapper for a joystick device
     * All public methods are safe to call with a null device
     */
    class CPPXOIS_API Joystick
    {
        friend class InputSystem;

    public:
        enum {DEFAULT_DEAD_ZONE = 6000};

        const OIS::JoyStick* GetJoystick() const;
        bool IsNull() const;
        bool PressedButton(int button) const;
        bool PressingButton(int button) const;
        bool ReleasedButton(int button) const;
        bool PressedAnyButton() const;
        bool PressingAnyButton() const;
        bool ReleasedAnyButton() const;
        bool PressedAxis(int axis, int direction, int deadZone) const;
        bool PressingAxis(int axis, int direction, int deadZone) const;
        bool ReleasedAxis(int axis, int direction, int deadZone) const;
        bool PressedAnyAxis() const;
        bool PressingAnyAxis() const;
        bool ReleasedAnyAxis() const;
        bool PressedPov(int povIndex, int povDirection, bool strict = false) const;
        bool PressingPov(int povIndex, int povDirection, bool strict = false) const;
        bool ReleasedPov(int povIndex, int povDirection, bool strict = false) const;
        bool PressedAnyPov() const;
        bool PressingAnyPov() const;
        bool ReleasedAnyPov() const;
        int GetPressedButton() const;
        int GetPressingButton() const;
        int GetReleasedButton() const;
        bool GetPressedAxisIndexAndDirection(int& index, int& direction) const;
        bool GetPressingAxisIndexAndDirection(int& index, int& direction) const;
        bool GetReleasedAxisIndexAndDirection(int& index, int& direction) const;
        bool GetPressedPovIndexAndDirection(int& index, int& direction) const;
        bool GetPressingPovIndexAndDirection(int& index, int& direction) const;
        bool GetReleasedPovIndexAndDirection(int& index, int& direction) const;
        void GetPressedButtons(InputSourceVector& inputSources) const;
        void GetPressingButtons(InputSourceVector& inputSources) const;
        void GetReleasedButtons(InputSourceVector& inputSources) const;
        void GetPressedAxisIndicesAndDirections(InputSourceVector& inputSources) const;
        void GetPressingAxisIndicesAndDirections(InputSourceVector& inputSources) const;
        void GetReleasedAxisIndicesAndDirections(InputSourceVector& inputSources) const;
        void GetPressedPovIndicesAndDirections(InputSourceVector& inputSources) const;
        void GetPressingPovIndicesAndDirections(InputSourceVector& inputSources) const;
        void GetReleasedPovIndicesAndDirections(InputSourceVector& inputSources) const;

    private:
        Joystick();

    private:
        void Set(OIS::JoyStick* joystick);
        void Update();

    private:
        static bool AxisActive(int value, int direction, int deadZone);
        static bool AxisActive(int value, int deadZone);
        static const OIS::Axis& GetJoystickAxis(const OIS::JoyStickState& joystickState, int axis);

    private:
        enum {BUTTON_COUNT = 16};
        enum {POV_COUNT = 4};

        OIS::JoyStick* joystick;
        OIS::JoyStickState previousJoystickState;
        bool updatedOnce;
    };

}

#endif